home *** CD-ROM | disk | FTP | other *** search
/ CGI How-To / CGI HOW-TO.iso / chap6 / 6_8 / newd_c / cgilib.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-06-15  |  12.5 KB  |  655 lines

  1.  
  2.  
  3. #include <stdlib.h>
  4. #include <stdio.h>
  5. #include <string.h>
  6. #include "cgilib.h"
  7.  
  8. #define NEEDS_ENCODE(x) (!(islower(x)||isupper(x)||isdigit(x)||(x==' ')))
  9.  
  10. void decodeData(char *queryString)
  11. {
  12.     /* Temporary variables */
  13.     int i = 0, j = 0, max = 0;
  14.     char c;
  15.     
  16.     /*
  17.     * Loop over the string.
  18.     * We use two loop indices,
  19.     * i is the actual current character
  20.     * j is used to move ahead when hex codes are found
  21.     * Two indices are needed since the string shrinks
  22.     * as hex-codes are turned into single characters.
  23.     * The loop ends when the '\0' character has been "copied".
  24.     */
  25.     if(queryString) max = strlen(queryString) + 1;
  26.     
  27.     for (i=0, j=0; j < max; ++i, ++j) 
  28.     {
  29.         /* If we have found hex-codes, j>i so copy the data down. */
  30.         
  31.         queryString[i] = queryString[j];
  32.         
  33.         if ('+' == queryString[i]) /* Convert pluses to spaces */
  34.         {
  35.             queryString[i] = ' ';
  36.         }
  37.         else if ('%' == queryString[j])/* Convert hex codes */
  38.         {
  39.             /*
  40.             * Get the first number of the hex code, and store it
  41.             * as a char.
  42.             */
  43.             
  44.             c = ((queryString[j+1] >= 'A') ?
  45.                         ((queryString[j+1] & 0xdf) - 'A') + 10 
  46.                         : (queryString[j+1] - '0'));
  47.             /*
  48.             * The first hex-code was the 16 places, so multiply
  49.             * c by 16.
  50.             */
  51.                             
  52.             c *= 16;
  53.             
  54.             /*
  55.             * Get the second number in the hex code and add that
  56.             * to the value of c.
  57.             * c now stores the correct character for the hex code.
  58.             */
  59.             c += ((queryString[j+2] >= 'A') ? 
  60.                         ((queryString[j+2] & 0xdf) - 'A') + 10 
  61.                         : (queryString[j+2] - '0'));
  62.                             
  63.             /* Replace the % char we copied with the actual character. */                
  64.             queryString[i] = c;
  65.     
  66.             /* Move j past the hex-code */
  67.             j += 2;
  68.         }
  69.     }
  70. }
  71.  
  72. /* encodeData() encodes a string for CGI */
  73. void encodeData(String aString)
  74. {
  75.   int x,size,l,push = 0;
  76.  
  77.   if(aString->string != NULL)
  78.     {
  79.       
  80.       /* figure out the size after encoding */
  81.       l=string_length(aString);
  82.       
  83.       for(x=0;x<l;x++)
  84.     {
  85.       if(NEEDS_ENCODE(aString->string[x]))
  86.         {
  87.           push+=2;
  88.         }
  89.       
  90.     }
  91.       
  92.       /* If we encountered characters to encode, encode them */
  93.       if(push != 0)
  94.     {
  95.       /* Grow as needed */
  96.       string_setSize(aString,l+push+1,0);
  97.       
  98.       /* Start encoded, back to front to reduce copying */
  99.       for(x=l;x>=0;x--)
  100.         {
  101.           
  102.           if((NEEDS_ENCODE(aString->string[x]))
  103.          &&(aString->string[x] != '\0'))
  104.            {
  105.              int tmp;
  106.              
  107.              tmp = (aString->string[x])%16;
  108.              aString->string[x+push] = (tmp>=10)? (tmp-10 + 'A') : (tmp+'0');
  109.              push--;
  110.  
  111.              tmp = (aString->string[x])/16;
  112.              aString->string[x+push] = (tmp>=10)? (tmp-10 + 'A') : (tmp+'0');
  113.  
  114.              push--;
  115.              aString->string[x+push] = '%';
  116.            }
  117.           else/*push the other char back*/
  118.         {
  119.           aString->string[x+push] = aString->string[x];
  120.         }
  121.         }
  122.     }
  123.  
  124.       /*Convert the spaces to pluses */
  125.       for(x=0;aString->string[x] != '\0';x++)
  126.     {
  127.       if(aString->string[x] == ' ') aString->string[x] = '+';
  128.     }
  129.       
  130.     } 
  131. }
  132.  
  133. /* 
  134.  * encodeDictionary() encodes a dictionary in the form
  135.  * of CGI data.
  136.  */
  137. String encodeDictionary(Dictionary dataDict)
  138. {
  139.   String returnString = 0;
  140.   DictState state;
  141.   char *key;
  142.   void *value;
  143.   String buffer;
  144.   int needAmp = 0;
  145.  
  146.   /* allocate the string */
  147.   returnString = string_alloc(512);
  148.   buffer = string_alloc(128);
  149.  
  150.   /* Create a dictionary state */
  151.   state = dict_initState(dataDict);
  152.  
  153.   /* Calculate how long the string will be */
  154.   
  155.   while(dict_nextState(&state))
  156.     {
  157.       key = state.curNode->key;
  158.  
  159.       /* If this isn't a multiple value, encode and append it */
  160.       if(key && strncmp(key,"A_",2))
  161.      {
  162.        value = state.curNode->value;
  163.  
  164.        string_setStringValue(buffer,key);
  165.        encodeData(buffer);
  166.  
  167.        if(needAmp)
  168.          {
  169.            string_appendChar(returnString,'&');
  170.          }
  171.  
  172.        string_appendString(returnString,buffer->string);
  173.        string_appendChar(returnString,'=');
  174.  
  175.        if(value)
  176.          {
  177.            string_setStringValue(buffer,value);
  178.            encodeData(buffer);
  179.          }
  180.        else
  181.          {
  182.            string_empty(buffer);
  183.          }
  184.  
  185.        string_appendString(returnString,buffer->string);
  186.  
  187.        needAmp = 1;
  188.      }
  189.     }
  190.  
  191.   string_free(buffer);
  192.   return returnString;
  193. }
  194.  
  195. int parseData(char *queryString, Dictionary dataDict)
  196. {
  197.     /* Temporary variables */
  198.     char *cursor = (char *)0;
  199.     
  200.     char *key = (char *)0, *value = (char *)0;
  201.     
  202.     char *sbegin = (char *)0, *send = (char *)0;
  203.     
  204.     int charsToCopy = 0;
  205.  
  206.     /* For example take queryString = "key=value&key1=value1" */
  207.     
  208.     if(queryString != (char *)0)
  209.       {
  210.         cursor = queryString;
  211.       }
  212.     else
  213.       {
  214.         return 0;
  215.       }
  216.  
  217.     do{/* Loop while we are finding keys */
  218.         
  219.         key = 0;/* Reset the tmp key */
  220.         
  221.         value = 0;/* Reset the tmp value */
  222.         
  223.         /*
  224.          * Reset the search pointer, sbegin 
  225.          *
  226.          *   key=value&key1=value1
  227.          *   ^         ^
  228.          *   |         |
  229.          *  pass 1    pass 2
  230.          *
  231.          */
  232.          
  233.         sbegin = cursor;
  234.         
  235.         /* 
  236.          * Move sbegin past any next special char, & or =
  237.          *
  238.          *   key=value&key1=value1
  239.          *   ^         ^
  240.          *   |         |
  241.          *  pass 1    pass 2
  242.          *
  243.          */
  244.         
  245.         sbegin += strspn(sbegin, "=&");
  246.         
  247.         /* Check if we are at the end of the query string */
  248.         
  249.         if(*sbegin == '\0') /* If at end, make the key and cursor = NULL */
  250.         {
  251.             cursor = (char *) 0;
  252.             key = cursor;
  253.         }
  254.         else /* Otherwise, find the key */
  255.         {
  256.             /* Reset the number of characters in the key */
  257.             
  258.             charsToCopy = 0;
  259.             
  260.             
  261.             /*
  262.              * Find the end of the key
  263.              *
  264.              *   key=value&key1=value1
  265.              *      ^          ^
  266.              *      |          |
  267.              *     pass 1     pass 2
  268.              *
  269.              */
  270.             send = sbegin + strcspn(sbegin,"=&");
  271.             
  272.             /* Check if the end of the key is the end of the string */
  273.             
  274.             if('\0' != (*send)) /* If not, calculate the length of key */
  275.             {
  276.                 /*
  277.                  * Find send past the =
  278.                  *
  279.                  *   key=value&key1=value1
  280.                  *       ^          ^
  281.                  *       |          |
  282.                  *      pass 1     pass 2
  283.                  *
  284.                  */
  285.                 send++;
  286.                 charsToCopy = strlen(sbegin) - strlen(send) - 1;
  287.             }
  288.             else /* Otherwise, key is whats left */
  289.             {
  290.                 charsToCopy = strlen(sbegin);
  291.             }
  292.             
  293.             /* Move the cursor to the end of the key */
  294.             
  295.             cursor = send;
  296.             
  297.             /* Allocate memory for the key */
  298.             
  299.             key = (char *) malloc(sizeof(char)*(charsToCopy +1));
  300.             
  301.             /* Copy the correst number of characters to the key string */
  302.             
  303.             strncpy(key,sbegin,charsToCopy);
  304.             
  305.             /* End the key string with a '\0' */
  306.             
  307.             key[charsToCopy] = '\0';
  308.         }
  309.         
  310.         /* If we have a key, try to read the value */
  311.         
  312.         if( key && (*key != '\0')){
  313.             
  314.             /*
  315.              * See if the next character is a &,
  316.              * if it is the key has an empty value.
  317.              */
  318.                 
  319.             if(('\0' != *cursor)
  320.                     &&('&' != *cursor))
  321.             {
  322.                 /*
  323.                  * Find the beginning of the value
  324.                  *
  325.                  *   key=value&key1=value1
  326.                  *       ^          ^
  327.                  *       |          |
  328.                  *      pass 1     pass 2
  329.                  *
  330.                  */
  331.                 
  332.                 sbegin = cursor;
  333.                 sbegin += strspn(sbegin, "=&");
  334.                 
  335.                 /* Check if we found a vlaue */
  336.                 
  337.                 if(*sbegin == '\0') /* If not set the value and cursor to 0 */
  338.                 {
  339.                     cursor = (char *) 0;
  340.                     value = cursor;
  341.                 }
  342.                 else /* Otherwise, find the value */
  343.                 {
  344.                     /* Reset the length of the value string */
  345.                 
  346.                     charsToCopy = 0;
  347.                     
  348.                     /*
  349.                      * Find the end of the value
  350.                      *
  351.                      *   key=value&key1=value1
  352.                      *            ^           ^
  353.                      *            |           |
  354.                      *           pass 1      pass 2
  355.                      *
  356.                      */
  357.                      
  358.                     send = sbegin + strcspn(sbegin,"=&");
  359.                     
  360.                     /* Check if the value is at the end of the string */
  361.                     
  362.                     if('\0' != (*send)) /* If not, calculate the length */
  363.                     {
  364.                         /*
  365.                         * Move send past the &
  366.                         *
  367.                         *   key=value&key1=value1
  368.                         *       ^          ^
  369.                         *       |          |
  370.                         *      pass 1     pass 2
  371.                         *
  372.                         */
  373.                         send++;
  374.                         charsToCopy = strlen(sbegin) 
  375.                                     - strlen(send) - 1;
  376.                     }
  377.                     else /* Otherwise, the length is from the start to '\0'*/
  378.                     {
  379.                         charsToCopy = strlen(sbegin);
  380.                     }
  381.                     
  382.                     /*
  383.                      * Reset the cursor
  384.                      *
  385.                      *   key=value&key1=value1
  386.                      *            ^           ^
  387.                      *            |           |
  388.                      *           pass 1      pass 2
  389.                      *
  390.                      */
  391.                     
  392.                     cursor = send;
  393.                     
  394.                     /* Allocate space for the value string */
  395.                     
  396.                     value = (char *) 
  397.                         malloc(sizeof(char)*(charsToCopy +1));
  398.                     
  399.                     /* Copy the value string, and add a '\0' */
  400.                     
  401.                     strncpy(value,sbegin,charsToCopy);
  402.                     value[charsToCopy] = '\0';
  403.                 }
  404.                 
  405.                 /*
  406.                  * Decode the key and value then,
  407.                  * print them
  408.                  */
  409.                  
  410.                 decodeData(key);
  411.                 decodeData(value);
  412.                 
  413.             }
  414.             else/* Key has an empty value */
  415.             {
  416.                 /*
  417.                  * Decode the key, then
  418.                  * print the key and an empty value
  419.                  */
  420.                 
  421.                 decodeData(key);
  422.                 
  423.                 value = malloc(sizeof(char) * 1);
  424.                 value[0] = '\0';
  425.             }
  426.             
  427.             /*
  428.              * Insert the value into the dictionary, but
  429.              * allow for multiple values on key.
  430.              * Put multiple values into an Array, with the key,
  431.              * A_key.
  432.              */
  433.              
  434.             /* Check if this is a multiple value */
  435.             if(dict_isKey(dataDict,key))
  436.             {
  437.                 /* Create the name for the array key */
  438.                 char *aName;
  439.                 
  440.                 aName = (char *) malloc((strlen(key)+3) * sizeof(char));
  441.                 
  442.                 sprintf(aName,"A_%s",key);
  443.                 
  444.                 /* Check if the array is in the dict, already */
  445.                 
  446.                 if(dict_isKey(dataDict,aName))
  447.                 {
  448.                     /* Add the new value to the array */
  449.                     
  450.                     Array theArray = 0;
  451.                     
  452.                     theArray = (Array) dict_valueForKey(dataDict,aName);
  453.                 
  454.                     array_addItem(theArray,value);
  455.                     
  456.                     /* Set the dictionaries value, to the latest */
  457.                     
  458.                     dict_setValueForKey(dataDict, key, value);
  459.                     
  460.                 }
  461.                 else /* If not, ... */
  462.                 {
  463.                     /* Create the array */
  464.                     
  465.                     Array theArray = 0;
  466.                     
  467.                     theArray = array_alloc(3);
  468.                     
  469.                     /* Add the first value to the array */
  470.                     
  471.                     array_addItem(theArray, dict_valueForKey(dataDict,key));
  472.                     
  473.                     /* Add the new value to the array */
  474.                     
  475.                     array_addItem(theArray,value);
  476.                     
  477.                     /* Set the dictionaries value, to the latest */
  478.                     
  479.                     dict_setValueForKey(dataDict, key, value);
  480.                     
  481.                     /* Add the array to the dictionary */
  482.                     
  483.                     dict_setValueForKey(dataDict, aName, (void *)theArray);
  484.                     
  485.                 }
  486.                 
  487.                 
  488.                 free(aName);
  489.             }
  490.             else /* If not, simple insert the value */
  491.             {
  492.                 dict_setValueForKey(dataDict, key, value);
  493.             }
  494.         
  495.         }
  496.     
  497.     }while(key && ('\0' != *key) && ('\0' != *cursor));
  498.         
  499.     return 1;/* Return 1 for success */
  500. }
  501.  
  502. void readGetData(char **aString)
  503. {
  504.     /* The data after it is read in */
  505.     char *queryString;
  506.     int len = 0;
  507.  
  508.     queryString = getenv("QUERY_STRING");
  509.  
  510.     if(queryString)
  511.       {    
  512.         len = strlen(queryString);
  513.  
  514.         *aString = malloc(sizeof(char) * len);
  515.  
  516.         strcpy(*aString,queryString);
  517.       }
  518.     else
  519.       {
  520.         len = 1;
  521.  
  522.         *aString = malloc(sizeof(char) * len);
  523.  
  524.         **aString = '\0';
  525.       }
  526. }
  527. void readPostData(char **aString)
  528. {
  529.     /* The data after it is read in */
  530.     char *queryString;
  531.     
  532.     /* The amount of data to read */
  533.     int contentLength;
  534.  
  535.     /* Temporary variables for storing envvar and iterating */
  536.     char *sizeString;
  537.     int i;
  538.     
  539.     /* Read the environment variable CONTENT_LENGTH */
  540.     
  541.     sizeString = getenv("CONTENT_LENGTH");
  542.     
  543.     
  544.     /* If the env. var. existed, convert the string to an integer */
  545.     
  546.     if (sizeString)
  547.     {
  548.         contentLength = atoi( sizeString );
  549.     }
  550.     else
  551.     {
  552.         contentLength = 0;
  553.     }
  554.     
  555.     /*
  556.      * If there is a non-zero amount of data, 
  557.      * alloc a string big enough to hold it.
  558.      */
  559.     if ( 0 != contentLength)
  560.     {
  561.         /* Notice that we add one to hold the null, '\0', character. */
  562.         queryString = (char *) malloc(sizeof(char) * (contentLength + 1) );
  563.     }
  564.     else
  565.     {
  566.         queryString = (char *) 0;
  567.     }
  568.     
  569.     /* If the malloc succeeded, read the data. */
  570.     
  571.     if ( queryString )
  572.     {
  573.         i = 0;
  574.         
  575.         /*
  576.          * Use fgetc to read the data, 
  577.          * iterating until the exact number of characters is read.
  578.         */
  579.         while( i < contentLength)
  580.         {
  581.                 queryString[ i++ ] = fgetc(stdin);
  582.         }
  583.         
  584.         /* Add the null, '\0', character to the end. */
  585.         
  586.         queryString[ i ] = '\0';
  587.     
  588.         /* Set the arguement to point to the data. */
  589.     
  590.         *aString = queryString;
  591.  
  592.     }
  593.     else
  594.         {
  595.         *aString = malloc(sizeof(char));
  596.  
  597.         **aString = '\0';
  598.         }
  599. }
  600.  
  601. void readData(char **aString)
  602. {
  603.     char *requestType = (char *) 0;
  604.     
  605.     
  606.     /* Read the request type */
  607.     
  608.     requestType = getenv("REQUEST_METHOD");
  609.     
  610.     /*
  611.      * If it is a GET request use readGetData,
  612.      * otherwise, if it is a POST request, use readPostData.
  613.      */
  614.      
  615.     if(requestType && !strcmp(requestType,"GET"))
  616.     {
  617.         readGetData(aString);
  618.     }
  619.     else if(requestType && !strcmp(requestType,"POST"))
  620.     {
  621.         readPostData(aString);
  622.     }
  623.     else
  624.     {
  625.              *aString = malloc(sizeof(char));
  626.  
  627.         **aString = '\0';
  628.     }
  629. }
  630.  
  631. Dictionary readParse()
  632. {
  633.     Dictionary returnData;
  634.     char *data;
  635.     
  636.     returnData = dict_alloc();
  637.       
  638.      readData(&data);
  639.           
  640.     if(data) parseData(data, returnData);
  641.     
  642.     if(data) free(data);
  643.     
  644.     return returnData;
  645. }
  646.  
  647.  
  648.  
  649.  
  650.  
  651.  
  652.  
  653.  
  654.  
  655.